﻿Public Class Misc
    Public Shared Function GeneratePassCode(ByVal length As Integer) As String
        Randomize()
        Dim clsRet As New System.Text.StringBuilder
        For i As Integer = 0 To length - 1
            Dim c As Char = Chr(33 + CInt(Rnd() * (255 - 33)))
            clsRet.Append(c)
        Next
        Return clsRet.ToString
    End Function

    Public Shared Function ToAndList(ByVal list As Generic.List(Of String)) As String
        Return ToAndList(list.ToArray)
    End Function
    Public Shared Function ToAndList(ByVal list As Generic.List(Of String), ByVal extraItem As String) As String
        Dim aList(list.Count) As String
        list.CopyTo(aList)
        aList(list.Count) = extraItem
        Return ToAndList(aList)
    End Function
    Public Shared Function ToAndList(ByVal list As Generic.List(Of String), ByVal extraItem As String, ByVal extraItem2 As String) As String
        Dim aList(list.Count + 1) As String
        list.CopyTo(aList)
        aList(list.Count) = extraItem
        aList(list.Count + 1) = extraItem2
        Return ToAndList(aList)
    End Function
    Public Shared Function ToAndList(ByVal list() As String) As String
        If list Is Nothing Then Return String.Empty
        Select Case list.Count
            Case 0
                Return String.Empty
            Case 1
                Return list(0)
            Case Is > 1
                Dim clsSB As New System.Text.StringBuilder
                For i As Integer = 0 To list.Count - 2
                    clsSB.Append(list(i))
                    clsSB.Append(", ")
                Next
                clsSB.Append("and ")
                clsSB.Append(list(list.Count - 1))
                Return clsSB.ToString
            Case Else
                Throw New NotSupportedException
        End Select
    End Function

    Public Shared Function GenerateUniqueId() As String
        Return String.Format("{0}{1}", System.Guid.NewGuid.ToString, System.Guid.NewGuid).Replace("-", "")
    End Function

    Public Shared Sub HandleException(ByVal owner As System.Windows.Forms.IWin32Window, ByVal exception As Exception)
        Dim sThreadName As String = String.Format("{0}:{1}", System.Threading.Thread.CurrentThread.Name, System.Threading.Thread.CurrentThread.ManagedThreadId)
        HandleException(owner, exception, sThreadName)
    End Sub
    Private Shared Sub HandleException(ByVal owner As System.Windows.Forms.IWin32Window, ByVal exception As Exception, ByVal threadName As String)
        Dim sText As String = String.Format("{0}{1}{1}{2}{1}{1}Thread: {3}", exception.Message, Environment.NewLine, exception.StackTrace, threadName)
        System.Windows.Forms.MessageBox.Show(owner, sText, "Unexpected Exception", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation)
    End Sub
    Private Delegate Sub HandleExceptionDelegate(ByVal exception As Exception, ByVal threadName As String)
    Public Shared Sub HandleException(ByVal exception As Exception)
        If Threading.MainGuiForm IsNot Nothing AndAlso Threading.MainGuiForm.InvokeRequired Then
            Dim sThreadName As String = String.Format("{0}:{1}", System.Threading.Thread.CurrentThread.Name, System.Threading.Thread.CurrentThread.ManagedThreadId)
            Dim clsD As New HandleExceptionDelegate(AddressOf HandleExceptionFromThread)
            Threading.MainGuiForm.Invoke(clsD, exception, sThreadName)
        Else
            HandleException(Threading.MainGuiForm, exception)
        End If
    End Sub
    Private Shared Sub HandleExceptionFromThread(ByVal exception As Exception, ByVal threadName As String)
        HandleException(Threading.MainGuiForm, exception, threadName)
    End Sub

    Public Shared Function ToReadableFileSize(ByVal size As Long) As String
        Dim aSuffix() As String = {"b", "Kb", "Mb", "Gb", "Tb"}
        Dim dSize As Double = size
        For i As Integer = 0 To aSuffix.Count - 1
            If dSize < 1024 Or i = aSuffix.Count - 1 Then
                If dSize = CDbl(CInt(dSize)) Then
                    Return String.Format("{0} {1}", CInt(dSize), aSuffix(i))
                Else
                    Return String.Format("{0:0.0} {1}", dSize, aSuffix(i))
                End If
            Else
                dSize = dSize / 1024
            End If
        Next
        Return "?"
    End Function
    Public Shared Function ToReadableSpeed(ByVal bytesPerSecond As Integer) As String
        Return String.Format("{0}/s", ToReadableFileSize(bytesPerSecond))
    End Function

    Public Shared Function ToHexStringNice(ByVal data() As Byte) As String
        If data Is Nothing Then Return String.Empty
        If data.Length <= 32 Then
            Return ToHexString(data, True)
        Else
            Dim clsSB As New System.Text.StringBuilder
            For i As Integer = 0 To 15
                If i <> 0 Then clsSB.Append(" "c)
                Dim s As String = Hex(data(i))
                If s.Length = 1 Then clsSB.Append("0"c)
                clsSB.Append(s)
            Next
            clsSB.Append(" ...")
            For i As Integer = data.Length - 16 To data.Length - 1
                clsSB.Append(" "c)
                Dim s As String = Hex(data(i))
                If s.Length = 1 Then clsSB.Append("0"c)
                clsSB.Append(s)
            Next
            Return clsSB.ToString
        End If
    End Function

    Public Shared Function ToLowerSafe(ByVal text As String) As String
        If text Is Nothing Then
            Return Nothing
        Else
            Return text.ToLower
        End If
    End Function

    Public Shared Function ToHexString(ByVal data() As Byte) As String
        If data Is Nothing Then Return String.Empty
        Return ToHexString(data, 0, data.Length, False)
    End Function
    Public Shared Function ToHexString(ByVal data() As Byte, ByVal addByteSpaceDivider As Boolean) As String
        If data Is Nothing Then Return String.Empty
        Return ToHexString(data, 0, data.Length, addByteSpaceDivider)
    End Function
    Public Shared Function ToHexString(ByVal data() As Byte, ByVal start As Integer, ByVal len As Integer) As String
        Return ToHexString(data, start, len, False)
    End Function
    Public Shared Function ToHexString(ByVal data() As Byte, ByVal start As Integer, ByVal len As Integer, ByVal addByteSpaceDivider As Boolean) As String
        If data Is Nothing Then Return String.Empty

        Dim clsSb As New System.Text.StringBuilder
        For i As Integer = start To start + len - 1
            If addByteSpaceDivider AndAlso clsSb.Length > 0 Then clsSb.Append(" "c)
            Dim s As String = Hex(data(i))
            If s.Length = 1 Then clsSb.Append("0"c)
            clsSb.Append(s)
        Next
        Return clsSb.ToString
    End Function
    Public Shared Function FindBalancedClosingPosition(ByVal text As String, ByVal start As Integer, ByVal openChar As Char, ByVal closeChar As Char) As Integer
        Dim iBalanceCount As Integer = 1
        For i As Integer = start To text.Length - 1
            If text.Chars(i) = openChar Then
                iBalanceCount += 1
            ElseIf text.Chars(i) = closeChar Then
                iBalanceCount -= 1
                If iBalanceCount = 0 Then Return i
            End If
        Next
        Return text.Length
    End Function

End Class
